initialize: keep the previous dispatch state when a policy throws - #95
Open
jll63 wants to merge 2 commits into
Open
initialize: keep the previous dispatch state when a policy throws#95jll63 wants to merge 2 commits into
jll63 wants to merge 2 commits into
Conversation
|
An automated preview of the documentation is available at https://95.openmethod.prtest3.cppalliance.org/libs/openmethod/doc/html/index.html If more commits are pushed to the pull request, the docs will rebuild at the same URL. 2026-09-02 22:33:23 UTC |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #95 +/- ##
===========================================
- Coverage 94.94% 93.09% -1.85%
===========================================
Files 99 22 -77
Lines 4373 1666 -2707
Branches 2168 508 -1660
===========================================
- Hits 4152 1551 -2601
+ Misses 162 66 -96
+ Partials 59 49 -10
... and 86 files with indirect coverage changes Continue to review full report in Codecov by Harness.
🚀 New features to boost your workflow:
|
write_global_data() patched every class' static_vptr, every overrider's `next` and each method's slots and strides to point into a local vector, then ran the policies' initialize, and only then swapped the vector into the registry's state. A policy that threw - fast_perfect_hash failing to find hash factors under throw_error_handler, or a plain bad_alloc - left all of those pointers dangling into a vector that unwinding had just freed, and clobbered the dispatch state of the previous initialize. Reorder it into stage, policies, commit. The dispatch data is built in a local vector and each class' v-table pointer is staged in its class_, where the policies read it; the policies run with their states saved in an RAII transaction that puts them back if one throws; the shared locations are written only after that, and nothing on that path can throw. A failed initialize() - a re-initialize after dlopen/dlclose included - leaves the previous tables in place, complete and consistent, though not marked initialized. The InitializeClass blueprint changes accordingly: vptr() returns the staged pointer by value, and static_vptr() returns the address that will receive it, for the policies that store pointers to v-table pointers. Fixes boostorg#81. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012QA4PCHE4oooe1ZtG9aKj7
BOOST_TEST(a == b) decomposes the comparison so that it can print both operands when it fails. For the `next` pointers that means streaming a function pointer, which is a Microsoft extension: clang-cl rejects it under /WX (-Wmicrosoft-cast), so test_initialize_transaction did not compile in any of the clang-win CI variants. Wrap the comparison in an extra pair of parentheses, as the neighbouring checks already do, so Boost.Test sees a bool. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VGX6XBwxEr1rqxGvAyvUgB
jll63
force-pushed
the
fix/initialize
branch
from
September 2, 2026 22:29
62515c7 to
6907b5c
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
(Written by Claude Code, on behalf of @jll63.)
Fixes #81.
write_global_data()patched every class'static_vptr, every overrider'snextand each method's slots and strides to point into a local vector, then ran the policies'initialize, and only then swapped the vector into the registry's state. A policy that threw -fast_perfect_hashfailing to find hash factors underthrow_error_handler, or a plainbad_alloc- left all of those pointers dangling into a vector that unwinding had just freed, and clobbered the dispatch state of the previousinitialize. Re-initialize afterdlopen/dlcloseis the documented flow, so this is reachable.Change
write_global_data()is now stage → policies → commit, with an RAII guard and no try/catch:class_instead of being written to*ci->static_vptr.detail::registry_state_transaction<Registry>, which copies the registry state'spoliciestuple whole on construction and moves it back on destruction unlesscommit()was called. The class and method lists need no saving (initializeonly reads them), anddispatch_datamust not be restored from a copy: the previousstatic_vptrs point into the live buffer, which is why it is only ever replaced at commit.nextpointers,static_vptr, then thedispatch_dataswap.A failed
initialize()leaves the previous tables in place, complete and consistent, though not marked initialized: they do not reflect the registrations that prompted the call, and after adlclosethey may point into unloaded code, sorequire_initialized()keeps refusing to dispatch until a call succeeds.The
InitializeClassblueprint changes accordingly:vptr()returns the staged pointer by value, and a newstatic_vptr()returns the address that will receive it, forindirect_vptrpolicies.vptr_vectorandvptr_mapuse it where they took&iter->vptr(); a user policy doing that now gets a compile error instead of a silently dangling pointer.Test
test/test_initialize_transaction.cpp: two registries (vptr_vector;vptr_map+indirect_vptr) and a policy, placed after the vptr policy, whoseinitializewrites to its state then throws on demand. Asserts that the dispatch buffer,static_vptr<Dog/Cat>,next<poke_dog>, the hash range, the vptr policy's state and the throwing policy's own state are unchanged; that dispatch throwsnot_initialized; that a laterinitialize()succeeds; and that a failing firstinitialize()leaves everything null/empty andfinalize()copes. Against the previous headers it fails 13 checks.Verified with CMake (gcc, Debug: 148/148) and b2 (gcc: 87/87); docs rendered (Antora + MrDocs).
🤖 Generated with Claude Code
https://claude.ai/code/session_012QA4PCHE4oooe1ZtG9aKj7